package com.alibaba.citrus.cr.price.ability.facade;

import com.alibaba.acm.shaded.com.google.common.collect.Lists;
import com.alibaba.acm.shaded.com.google.common.collect.Maps;
import com.alibaba.acm.shaded.com.google.common.collect.Sets;
import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.annotation.ProcessInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.exception.ProcessException;
import com.alibaba.citrus.cr.common.lock.RedisLock;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.price.ability.functions.PlatformCodeFlagEnum;
import com.alibaba.citrus.cr.price.ability.functions.constant.ActivityFeatureKeyEnum;
import com.alibaba.citrus.cr.price.ability.functions.entity.activity.*;
import com.alibaba.citrus.cr.price.ability.functions.factory.activity.ActivityFactory;
import com.alibaba.citrus.cr.price.ability.functions.factory.activity.process.ActivityProcessManager;
import com.alibaba.citrus.cr.price.ability.functions.factory.price.process.PropertyProcessManager;
import com.alibaba.citrus.cr.price.repository.ActivityQueryRepository;
import com.alibaba.citrus.cr.price.repository.ActivityWriteRepository;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.model.dto.ScItemSDO;
import com.epoch.app.crb2btradecenter.model.dto.TradeMessageSDO;
import com.epoch.app.crb2btradecenter.sdo.OrderLineSDO;
import com.epoch.app.crb2btradecenter.sdo.OrderSDO;
import com.epoch.app.crforecastsales.domian.activityterm.model.ActivityTerm;
import com.epoch.app.crforecastsales.domian.activitytitle.model.ActivityTitle;
import com.epoch.app.crforecastsales.model.dto.ActivitySDO;
import com.epoch.app.crpricecenter.api.activitywrite.dto.BackOffActivityRequest;
import com.epoch.app.crpricecenter.api.activitywrite.service.ActivityWriteService;
import com.epoch.app.crpricecenter.contants.CrPriceCenterConstants;
import com.epoch.app.crpricecenter.dto.request.*;
import com.epoch.app.crpricecenter.dto.response.*;
import com.epoch.app.crpricecenter.enums.DimensionPropertyEnum;
import com.epoch.app.crpricecenter.model.dto.ActivityResponse;
import com.epoch.app.crpricecenter.model.dto.CoverActivityRequest;
import com.epoch.app.crpricecenter.model.dto.ParticipateActivityRequest;
import com.epoch.app.crpricecenter.model.dto.QueryActivityRequest;
import com.epoch.app.crpricecenter.sdo.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author hanguo
 * @date 2021/10/14
 * @Description 促销活动同步接口
 */
@Service
@Primary
public class ActivityWriteServiceImpl implements ActivityWriteService {

    private static Log log = Log.getLogger(ActivityWriteServiceImpl.class);

    @Resource
    private ActivityWriteRepository activityWriteRepository;

    @Resource
    private ActivityQueryRepository activityQueryRepository;

    //这个地方不能改
    @Resource
    private ActivityQueryServiceImpl activityQueryServiceImpl;

    @Autowired
    private ApplicationContext applicationContext;

    @Resource
    private ActivityProcessManager manager;

    @Resource
    private PropertyProcessManager propertyProcessManager;

    /**
     * 活动占用前缀
     */
    private final static String ACTIVITY_PARTICIPATE = "activity_participate_";
    /**
     * 活动回补前缀
     */
    private final static String ACTIVITY_COVER = "activity_cover_";

    /**
     * 活动扩展表更新前缀
     */
    private final static String ACTIVITY_EXT_UPDATE = "activity_ext_update_";

    /**
     * 超时时间
     */
    private final static int TIMEOUT_MSECS = 3 * 1000;
    /**
     * 过期时间
     */
    private final static int EXPIRE_MSECS = 24 * 60 * 60 * 1000;

    /**
     * 超时时间（同步活动扩展表使用）
     */
    private final static int TIMEOUT_MSECS_ACTIVITY_TITLE_EXT = 1 *1000;

    /**
     * 过期时间（同步活动扩展表使用）
     */
    private final static int EXPIRE_MSECS_ACTIVITY_TITLE_EXT = 2 *1000;

    /**
     *
     * 时候计算活动金额
     */
    private static String  ACTIVITY_GIFT_HAVE_FEE="activityGiftHaveFee";
    /**
     * 是否存在满量赠选中
     * */
    private static String  ACTIVITY_FULL_GIFT_CHOOSE="activityFullGiftChoose";
    /**
     * 是否包含满量赠活动
     * */
    private static String  ACTIVITY_FULL_GIFT_HAVE="activityFullGiftHave";
    /**
     * 活动类型
     * */
    private static String  ACTIVITY_TYPE="activityType";
    /**
     * 是否选中活动
     * */
    private static String  ACTIVITY_SELECT_FLAG="activitySelectFlag";
    /**
     * 预报订单号
     */
    private static String FORECAST_ORDER_BIZ_ID = "forecastOrderBizId";

    private static String CODE_FLAG = "codeFlag";
    /**
     * 内外码转换 value
     */
    private static String INNER_CODE_TO_OUT_CODE = "inner_code_to_out_code";
    private static String OUT_CODE_TO_INNER_CODE = "out_code_to_inner_code";

    @FacadeInvoker("同步活动抬头数据")
    @Override
    public Result syncActivityTitleData(SyncActivityTitleDataRequest syncActivityTitleDataRequest) {
        if (StringUtils.isNotBlank(syncActivityTitleDataRequest.getFeatures())){
            syncActivityTitleDataRequest.setSender(JSONObject.parseObject(syncActivityTitleDataRequest.getFeatures()).get("dataSource").toString());
        }
        ActivityTitleSDO activityTitleSDO = new ActivityTitleSDO();
        BeanUtils.copyProperties(syncActivityTitleDataRequest, activityTitleSDO);
        try {
            Boolean result = activityWriteRepository.createActivityTitleData(activityTitleSDO);
            if (result) {
                return Result.success("同步成功");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#syncActivityTitleData_fail");
            log.error("同步失败:" + JSONObject.toJSONString(activityTitleSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
        log.error("ActivityWriteServiceImpl#syncActivityTitleData_fail");
        return Result.fail("OTS-08-001-01-01-001", "数据入库失败");
    }

    @FacadeInvoker("同步活动明细数据")
    @Override
    public Result syncActivityTermData(SyncActivityTermDataRequest syncActivityTermDataRequest) {
        ActivityTermSDO activityTermSDO = new ActivityTermSDO();
        BeanUtils.copyProperties(syncActivityTermDataRequest, activityTermSDO);
        try {
            Boolean result = activityWriteRepository.createActivityTermData(activityTermSDO);
            if (result) {
                return Result.success("同步成功");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#syncActivityTermData_fail");
            log.error("同步失败" + JSONObject.toJSONString(activityTermSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
        log.error("ActivityWriteServiceImpl#syncActivityTermData_fail");
        return Result.fail("OTS-08-002-01-01-001", "数据入库失败");

    }

    @FacadeInvoker("同步活动客户关系数据")
    @Override
    public Result syncActivityClientRelationData(SyncActivityClientRelationDataRequest syncActivityClientRelationDataRequest) {
        ActivityClientRelationSDO activityClientRelationSDO = new ActivityClientRelationSDO();
        BeanUtils.copyProperties(syncActivityClientRelationDataRequest, activityClientRelationSDO);
        if (StringUtils.isNotEmpty(syncActivityClientRelationDataRequest.getFeatures())){
            activityClientRelationSDO.setSender(JSONObject.parseObject(syncActivityClientRelationDataRequest.getFeatures()).get("dataSource").toString());
        }

        try {
            Boolean result = activityWriteRepository.createActivityClientRelationData(activityClientRelationSDO);
            if (result) {
                return Result.success("同步成功");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#syncActivityClientRelationData_fail");
            log.error("同步失败" + JSONObject.toJSONString(activityClientRelationSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
        log.error("ActivityWriteServiceImpl#syncActivityClientRelationData_fail");
        return Result.fail("OTS-08-003-01-01-001", "数据入库失败");

    }

    @FacadeInvoker("同步活动抬头扩展数据")
    @Override
    public Result syncActivityTitleExtData(SyncActivityTitleExtDataRequest syncActivityTitleExtDataRequest) {

        //加开关
        if ("TRUE".equalsIgnoreCase(CrPriceCenterConstants.ACTIVITY_EXT_UPDATE_SWITCH())) {
            log.info(ACTIVITY_EXT_UPDATE + "1");
            String redisKey = ACTIVITY_EXT_UPDATE
                    + "_" + syncActivityTitleExtDataRequest.getActivityNoteId()
                    + "_" + syncActivityTitleExtDataRequest.getApplyItemQuantity()
                    + "_" + syncActivityTitleExtDataRequest.getApplyFee()
                    + "_" + syncActivityTitleExtDataRequest.getSalesUnit()
                    + "_" + syncActivityTitleExtDataRequest.getCurrency();

            try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(), redisKey, TIMEOUT_MSECS_ACTIVITY_TITLE_EXT, EXPIRE_MSECS_ACTIVITY_TITLE_EXT)) {
                log.info(ACTIVITY_EXT_UPDATE + "2");
                boolean locked = lock.lock();
                if (!locked) {
                    log.error("获取分布式锁失败：ActivityWriteServiceImpl#syncActivityTitleExtData.getLock.fail RedisKey=" + redisKey);
                    log.error("ActivityWriteServiceImpl#syncActivityTitleExtData_lock.lock_fail");
                    return Result.fail("OTS-08-002-01-16-010", "系统繁忙，请稍后重试!");
                }

                ActivityTitleExtSDO activityTitleExtSDO = new ActivityTitleExtSDO();
                BeanUtils.copyProperties(syncActivityTitleExtDataRequest, activityTitleExtSDO);
                try {
                    Boolean result = activityWriteRepository.createActivityTitleExtData(activityTitleExtSDO);
                    if (result) {
                        return Result.success("修改成功");
                    }
                } catch (Exception e) {
                    log.error("ActivityWriteServiceImpl#syncActivityTitleExtData_fail");
                    log.error("修改失败" + JSONObject.toJSONString(activityTitleExtSDO), e);
                    return Result.fail(e.getMessage(), e.getMessage());
                }
                log.error("ActivityWriteServiceImpl#syncActivityTitleExtData_fail");
                return Result.fail("OTS-08-005-01-01-001", "数据入库失败");
            } catch (Exception e) {
                log.error("ActivityWriteServiceImpl#syncActivityTitleExtData_getLock_fail");
                log.error("修改失败---加锁失败!", e);
            }

        } else {

            ActivityTitleExtSDO activityTitleExtSDO = new ActivityTitleExtSDO();
            BeanUtils.copyProperties(syncActivityTitleExtDataRequest, activityTitleExtSDO);
            try {
                Boolean result = activityWriteRepository.createActivityTitleExtData(activityTitleExtSDO);
                if (result) {
                    return Result.success("修改成功");
                }
            } catch (Exception e) {
                log.error("ActivityWriteServiceImpl#syncActivityTitleExtData_fail");
                log.error("修改失败" + JSONObject.toJSONString(activityTitleExtSDO), e);
                return Result.fail(e.getMessage(), e.getMessage());
            }
            log.error("ActivityWriteServiceImpl#syncActivityTitleExtData_fail");
            return Result.fail("OTS-08-005-01-01-001", "数据入库失败");

        }

        //逻辑由上面的开关控制
        return null;
    }

    @FacadeInvoker("同步活动原品关系数据")
    @Override
    public Result syncActivityTermItemRelationData(SyncActivityTermItemRelationDataRequest syncActivityTermItemRelationDataRequest) {
        ActivityTermItemRelationSDO activityTermItemRelationSDO = new ActivityTermItemRelationSDO();
        BeanUtils.copyProperties(syncActivityTermItemRelationDataRequest, activityTermItemRelationSDO);
        try {
            Boolean result = activityWriteRepository.createActivityTermItemRelationData(activityTermItemRelationSDO);
            if (result) {
                return Result.success(true, "同步成功");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#syncActivityTermItemRelationData_fail");
            log.error("同步失败" + JSONObject.toJSONString(activityTermItemRelationSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
        log.error("ActivityWriteServiceImpl#syncActivityTermItemRelationData_fail");
        return Result.fail("OTS-08-006-01-01-001", "数据入库失败");

    }

    @FacadeInvoker("同步活动赠品关系数据")
    @Override
    public Result syncActivityTermGiftRelationData(SyncActivityTermGiftRelationDataRequest syncActivityTermGiftRelationDataRequest) {
        ActivityTermGiftRelationSDO activityTermGiftRelationSDO = new ActivityTermGiftRelationSDO();
        BeanUtils.copyProperties(syncActivityTermGiftRelationDataRequest, activityTermGiftRelationSDO);
        try {
            Boolean result = activityWriteRepository.createActivityTermGiftRelationData(activityTermGiftRelationSDO);
            if (result) {
                return Result.success(true, "同步成功");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#syncActivityTermGiftRelationData_fail");
            log.error("同步失败" + JSONObject.toJSONString(activityTermGiftRelationSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
        log.error("ActivityWriteServiceImpl#syncActivityTermGiftRelationData_fail");
        return Result.fail("OTS-08-007-01-01-001", "数据入库失败");

    }

    @FacadeInvoker("同步坎级信息数据")
    @Override
    public Result syncSegmentedActivityTermData(SyncSegmentedActivityTermDataRequest syncSegmentedActivityTermDataRequest) {
        SegmentedActivityTermSDO segmentedActivityTermSDO = new SegmentedActivityTermSDO();
        BeanUtils.copyProperties(syncSegmentedActivityTermDataRequest, segmentedActivityTermSDO);
        try {
            Boolean result = activityWriteRepository.createSegmentedActivityTermData(segmentedActivityTermSDO);
            if (result) {
                return Result.success(true, "同步成功");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#syncSegmentedActivityTermData_fail");
            log.error("同步失败" + JSONObject.toJSONString(segmentedActivityTermSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
        log.error("ActivityWriteServiceImpl#syncSegmentedActivityTermData_fail");
        return Result.fail("OTS-08-008-01-01-001", "数据入库失败");
    }

    @FacadeInvoker("同步操作流水数据")
    @Override
    public Result syncOperateJournalFlowData(SyncOperateJournalFlowDataRequest syncOperateJournalFlowDataRequest) {
        OperateJournalFlowSDO operateJournalFlowSDO = new OperateJournalFlowSDO();
        BeanUtils.copyProperties(syncOperateJournalFlowDataRequest, operateJournalFlowSDO);
        try {
            Boolean result = activityWriteRepository.createOperateJournalFlowData(operateJournalFlowSDO);
            if (result) {
                return Result.success(true, "同步成功");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#syncOperateJournalFlowData_fail");
            log.error("同步失败" + JSONObject.toJSONString(operateJournalFlowSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
        log.error("ActivityWriteServiceImpl#syncOperateJournalFlowData_fail");
        return Result.fail("OTS-08-009-01-01-001", "数据入库失败");
    }

    @FacadeInvoker("修改活动抬头数据")
    @Override
    public Result updateActivityTitleData(UpdateActivityTitleDataRequest updateActivityTitleDataRequest) {
        // 数据来源 sender
        String sender = "";
        if (StringUtils.isNotEmpty(updateActivityTitleDataRequest.getFeatures())){
            sender = JSONObject.parseObject(updateActivityTitleDataRequest.getFeatures()).getString("dataSource");
        }

        ActivityTitleSDO activityTitleSDO = new ActivityTitleSDO();
        BeanUtils.copyProperties(updateActivityTitleDataRequest, activityTitleSDO);

        //活动结束时间修改
        activityTitleSDO.setActivityEndDate(DateUtils.getLatestTime(activityTitleSDO.getActivityEndDate()));
        activityTitleSDO.setOrderEndDate(DateUtils.getLatestTime(activityTitleSDO.getOrderEndDate()));
        activityTitleSDO.setSender(sender);
        try {
            Boolean result = activityWriteRepository.updateActivityTitleData(activityTitleSDO);
            if (result) {
                return Result.success(true, "修改成功");
            } else {
                log.error("ActivityWriteServiceImpl#updateActivityTitleData_fail");
                return Result.success("没有数据发生改变，可能是当前传入的activityId在表里面无记录");
            }
        } catch (Exception e) {
            log.error("ActivityWriteServiceImpl#updateActivityTitleData_fail");
            log.error("同步失败" + JSONObject.toJSONString(activityTitleSDO), e);
            return Result.fail(e.getMessage(), e.getMessage());
        }
    }

    /**
     * 参加活动_有转码功能的接口 内部->外部
     *
     * @param participateActivityRequest 请求
     * @return
     */
    @Override
    @FacadeInvoker(value = "参加活动", errorCode = "OTS-08-002-01-16-002")
    public Result<ParticipateInActivityResponse> participateActivityExpand(ParticipateActivityRequest participateActivityRequest) {

        checkActivityParam(participateActivityRequest);
        ParticipateActivityRequest newRequest = new ParticipateActivityRequest();
        //BeanUtils.copyProperties(participateActivityRequest, newRequest);
        copyValue(participateActivityRequest, newRequest);

        checkActivityParam(newRequest);

        if (Objects.isNull(newRequest) || MapUtils.isEmpty(newRequest.getFeatures()) ||
                StringUtils.isBlank(newRequest.getFeatures().get("codeFlag"))) {
            log.error("请传编码转换标识，内部转外部:inner_code_to_out_code,外部转内部:out_code_to_inner_code" +
                    "newRequest", JSONObject.toJSONString(newRequest));
            log.error("ActivityWriteServiceImpl#participateActivityExpand_fail");
            throw new FacadeException("OTS-08-001-01-16-018");
        }

        if (PlatformCodeFlagEnum.OUT_CODE_TO_INNER_CODE.getCode().equals(newRequest.getFeatures().get("codeFlag"))) {
            return applicationContext.getBean(ActivityWriteServiceImpl.class).participateActivity(newRequest);
        }

        if (!PlatformCodeFlagEnum.INNER_CODE_TO_OUT_CODE.getCode().equals(newRequest.getFeatures().get("codeFlag"))) {
            log.error("请传正确的编码转换标识，内部转外部:inner_code_to_out_code,外部转内部:out_code_to_inner_code"
                    + "newRequest", JSONObject.toJSONString(newRequest));
            log.error("ActivityWriteServiceImpl#participateActivityExpand_fail");
            throw new FacadeException("OTS-08-001-01-16-019");
        }

        //获取所有的内外部编码映射关系
        Set<String> itemOutCodeList = Sets.newHashSet();
        newRequest.getParticipateActivityInfoList().stream().forEach(item -> {
            ParticipateActivityTermRequest participateActivityTermRequest = item.getParticipateActivityTermRequest();
            ActivityItemInfo activityItemInfo = participateActivityTermRequest.getItem();
            String itemId = activityItemInfo.getItemId();
            if (StringUtils.isBlank(itemId)) {
                log.error("物料编码不允许为空", JSONObject.toJSONString(participateActivityTermRequest));
                log.error("ActivityWriteServiceImpl#participateActivityExpand_fail");
                throw new FacadeException("OTS-08-001-01-16-020");
            }
            itemOutCodeList.add(activityItemInfo.getItemId());
            //赠品列表不为空，添加进去并计算
            if (CollectionUtils.isNotEmpty(participateActivityTermRequest.getGiftList())) {
                List<String> giftItemIds = participateActivityTermRequest.getGiftList().stream().map(x -> x.getItemId()).collect(Collectors.toList());
                itemOutCodeList.addAll(giftItemIds);
            }
        });
        Map<String, String> itemMap = propertyProcessManager.getPropertyProcess(DimensionPropertyEnum.MATERIAL_CODE.getKey())
                .obtainInnerCodeAndOuterCodeMap(itemOutCodeList.stream().collect(Collectors.toList()), true);
//        Map<String, ScItemSDO> itemMap = activityQueryServiceImpl.obtainItemMap(itemOutCodeList.stream().collect(Collectors.toList()), true);

        if (MapUtils.isEmpty(itemMap)) {
            log.error("未查询到货品外部编码，请排查是否存在映射关系" + JSONObject.toJSONString(newRequest));
            log.error("ActivityWriteServiceImpl#participateActivityExpand_fail");
            throw new FacadeException("OTS-08-001-01-16-021");
        }

        //参数转换，内部编码转外部编码
        List<ParticipateActivityInfoRequest> participateActivityInfoRequests = newRequest.
                getParticipateActivityInfoList().stream().map(participateActivityInfoRequest -> {
                    ParticipateActivityInfoRequest participateActivityInfoRequestItem = new ParticipateActivityInfoRequest();
                    BeanUtils.copyProperties(participateActivityInfoRequest, participateActivityInfoRequestItem);
                    ParticipateActivityTermRequest participateActivityTermRequest = participateActivityInfoRequest.getParticipateActivityTermRequest();

                    ParticipateActivityTermRequest participateActivityTermRequestItem = new ParticipateActivityTermRequest();
                    BeanUtils.copyProperties(participateActivityTermRequest, participateActivityTermRequestItem);
                    ActivityItemInfo activityItemInfo = participateActivityTermRequest.getItem();
                    String itemOutCode = itemMap.get(activityItemInfo.getItemId());
                    if (StringUtils.isBlank(itemOutCode)) {
                        log.error("未查询到货品外部编码，请排查是否存在映射关系", JSONObject.toJSONString(activityItemInfo));
                        log.error("ActivityWriteServiceImpl#participateActivityExpand_fail");
                        throw new FacadeException("OTS-08-001-01-16-021");
                    }
                    activityItemInfo.setItemId(itemOutCode);
                    participateActivityTermRequestItem.setItem(activityItemInfo);
                    if (CollectionUtils.isNotEmpty(participateActivityTermRequest.getGiftList())) {
                        List<ActivityItemInfo> activityGiftInfos = participateActivityTermRequest.getGiftList()
                                .stream().map(itemInfo -> {
                                    ActivityItemInfo info = new ActivityItemInfo();
                                    BeanUtils.copyProperties(itemInfo, info);
                                    String giftOutCode = itemMap.get(itemInfo.getItemId());
//                                    ScItemSDO scItemInfoSDO = itemMap.get(itemInfo.getItemId());
                                    if (StringUtils.isBlank(giftOutCode)) {
                                        log.error("未查询到货品外部编码，请排查是否存在映射关系={}", JSONObject.toJSONString(itemInfo));
                                        log.error("ActivityWriteServiceImpl#participateActivityExpand_fail");
                                        throw new FacadeException("OTS-08-001-01-16-021");
                                    }
                                    info.setItemId(giftOutCode);
                                    return info;
                                }).collect(Collectors.toList());
                        participateActivityTermRequestItem.setGiftList(activityGiftInfos);
                    }

                    participateActivityInfoRequestItem.setParticipateActivityTermRequest(participateActivityTermRequestItem);

                    return participateActivityInfoRequestItem;
                }).collect(Collectors.toList());
        newRequest.setParticipateActivityInfoList(participateActivityInfoRequests);

        Result<ParticipateInActivityResponse> result = applicationContext.getBean(ActivityWriteServiceImpl.class).participateActivity(newRequest);

        //外部转回内部
        if (Objects.isNull(result.getResult()) || CollectionUtils.isEmpty(result.getResult().getParticipateActivityResponseList())) {
            return result.isSuccess() ? Result.success(result.getResult(), result.getMessage()) :
                    Result.fail(result.getErrorCode(), result.getMessage());
        }

        List<String> outCodeItemIds = result.getResult().getParticipateActivityResponseList().stream().
                map(item -> item.getItemId()).collect(Collectors.toSet()).stream().collect(Collectors.toList());
        //获取外部编码和货品的对应关系
        Map<String, String> outCodeItemMap = propertyProcessManager.getPropertyProcess(DimensionPropertyEnum.MATERIAL_CODE.getKey())
                .obtainInnerCodeAndOuterCodeMap(outCodeItemIds, false);
        ParticipateInActivityResponse participateInActivityResponse = result.getResult();


//        外部编码转内部编码
        List<ParticipateActivityInfoResponse> participateActivityInfoResponses = participateInActivityResponse.
                getParticipateActivityResponseList().stream().map(item -> {
                    ParticipateActivityInfoResponse participateActivityInfoResponse = new ParticipateActivityInfoResponse();
                    BeanUtils.copyProperties(item, participateActivityInfoResponse);
                    String itemInnerCode = outCodeItemMap.get(item.getItemId());
                    participateActivityInfoResponse.setItemId("未查询到物料内部编码,请排查是否存在映射关系:" + item.getItemId());
                    if (StringUtils.isNotBlank(itemInnerCode)) {
                        participateActivityInfoResponse.setItemId(itemInnerCode);
                    }
                    participateActivityInfoResponse.setParticipateSuccessItemCount(item.getParticipateSuccessItemCount());
                    return participateActivityInfoResponse;
                }).collect(Collectors.toList());
        participateInActivityResponse.setParticipateActivityResponseList(participateActivityInfoResponses);

        return result;
    }

    private void copyValue(ParticipateActivityRequest oldValue, ParticipateActivityRequest newValue) {
        newValue.setFeatures(oldValue.getFeatures());

        List<ParticipateActivityInfoRequest> newParticipateActivityInfoRequest = oldValue.getParticipateActivityInfoList().stream().map(item -> {
                    ParticipateActivityInfoRequest participateActivityInfoRequest = new ParticipateActivityInfoRequest();
                    participateActivityInfoRequest.setActivityId(item.getActivityId());
                    participateActivityInfoRequest.setActivityUseTime(item.getActivityUseTime());
                    participateActivityInfoRequest.setMainOrderId(item.getMainOrderId());
                    participateActivityInfoRequest.setSubOrderId(item.getSubOrderId());
                    participateActivityInfoRequest.setClientId(item.getClientId());
                    participateActivityInfoRequest.setDeliveryDate(item.getDeliveryDate());
                    participateActivityInfoRequest.setOrderType(item.getOrderType());
                    participateActivityInfoRequest.setSequenceNo(item.getSequenceNo());
                    participateActivityInfoRequest.setFeatures(item.getFeatures());


                    ParticipateActivityTermRequest newTermRequest = new ParticipateActivityTermRequest();
                    ParticipateActivityTermRequest oldTermRequest = item.getParticipateActivityTermRequest();
                    newTermRequest.setActivityTermId(oldTermRequest.getActivityTermId());
                    newTermRequest.setVersion(oldTermRequest.getVersion());
                    newTermRequest.setSpecialOfferPrice(oldTermRequest.getSpecialOfferPrice());
                    newTermRequest.setCommonGroupFlag(oldTermRequest.getCommonGroupFlag());


                    ActivityItemInfo oldItem = oldTermRequest.getItem();
                    ActivityItemInfo newItem = new ActivityItemInfo();
                    newItem.setActivityOccupyFee(oldItem.getActivityOccupyFee());
                    newItem.setItemName(oldItem.getItemName());
                    newItem.setItemId(oldItem.getItemId());
                    newItem.setItemQuantity(oldItem.getItemQuantity());
                    newItem.setItemPrice(oldItem.getItemPrice());
                    newItem.setStockUnit(oldItem.getStockUnit());
                    newItem.setConversionUnit(oldItem.getConversionUnit());
                    newItem.setSalesUnit(oldItem.getSalesUnit());
                    newTermRequest.setItem(newItem);


                    List<ActivityItemInfo> oldGiftList = oldTermRequest.getGiftList();
                    if (CollectionUtils.isNotEmpty(oldGiftList)) {
                        List<ActivityItemInfo> newGiftList = oldGiftList.stream().map(gift -> {
                            ActivityItemInfo newGift = new ActivityItemInfo();
                            newGift.setActivityOccupyFee(gift.getActivityOccupyFee());
                            newGift.setItemName(gift.getItemName());
                            newGift.setItemId(gift.getItemId());
                            newGift.setItemQuantity(gift.getItemQuantity());
                            newGift.setItemPrice(gift.getItemPrice());
                            newGift.setStockUnit(gift.getStockUnit());
                            newGift.setConversionUnit(gift.getConversionUnit());
                            newGift.setSalesUnit(gift.getSalesUnit());
                            newGift.setDisableChooseFlag(gift.getDisableChooseFlag());
                            return newGift;
                        }).collect(Collectors.toList());

                        newTermRequest.setGiftList(newGiftList);
                    }

                    participateActivityInfoRequest.setParticipateActivityTermRequest(newTermRequest);

                    return participateActivityInfoRequest;
                }
        ).collect(Collectors.toList());
        newValue.setParticipateActivityInfoList(newParticipateActivityInfoRequest);
    }

    /**
     * 获取价格
     *
     * @param participateActivityRequest
     * @param queryActivityResult
     * @return
     */
    @ProcessInvoker
    private ParticipateInActivityResponse checkSpecialPriceAndGift(ParticipateActivityRequest participateActivityRequest,
                                                                   Result<ActivityResponse> queryActivityResult) {
        if (!queryActivityResult.isSuccess() || Objects.isNull(queryActivityResult.getResult())) {
            log.error("打印下查询活动后的结果={}", queryActivityResult);
            log.error("ActivityWriteServiceImpl#checkSpecialPriceAndGift_fail");
            throw new FacadeException("OTS-08-002-01-16-004");
        }

        //校验参数列表不能为空
        if (CollectionUtils.isEmpty(participateActivityRequest.getParticipateActivityInfoList())) {
            log.error("参加活动入参列表为空！入参={}", participateActivityRequest);
            log.error("ActivityWriteServiceImpl#checkSpecialPriceAndGift_fail");
            throw new FacadeException("OTS-08-002-01-16-005");
        }

        List<ActivityInfoResponse> activityInfoResponseList = queryActivityResult.getResult().getActivityInfoResponseList();

        // 活动直接根据活动ID进行匹配，一盘货订单的request里存的是外部单号，无法匹配成功
        Map<String, ActivityInfoResponse> responseMap = Nullable.stream(activityInfoResponseList).collect(Collectors.toMap(
//                e -> e.getMainOrderId() + "_" + e.getSubOrderId() + "_" + e.getActivityId(), Function.identity()));
                ActivityInfoResponse::getActivityId, Function.identity()));

        ParticipateInActivityResponse participateInActivityResponse = new ParticipateInActivityResponse();
        List<ParticipateActivityInfoResponse> lists = new ArrayList<>();
        participateActivityRequest.getParticipateActivityInfoList().forEach(request -> {

            //封装响应体参数
            ParticipateActivityInfoResponse participateActivityInfoResponse = new ParticipateActivityInfoResponse();
            participateActivityInfoResponse.setActivityId(request.getActivityId());
            participateActivityInfoResponse.setActivityTermId(request.getParticipateActivityTermRequest().getActivityTermId());
            participateActivityInfoResponse.setSubOrderId(request.getSubOrderId());
            participateActivityInfoResponse.setMainOrderId(request.getMainOrderId());
            participateActivityInfoResponse.setOrderType(request.getOrderType());


//            String key = request.getMainOrderId() + "_" + request.getSubOrderId() + "_" + request.getActivityId();
            String key = request.getActivityId();
            ActivityInfoResponse infoResponse = responseMap.get(key);
            if (Objects.isNull(infoResponse)) {
                //1. 写错误日志
                log.error("1.未查询到促销活动，参加活动失败，入参 = {}", JSONObject.toJSONString(request));
                participateActivityInfoResponse.setParticipateResult(false);
                participateActivityInfoResponse.setParticipateResultMsg("参加活动失败，未查询到促销活动！");

            } else {
                ParticipateActivityTermRequest termRequest = request.getParticipateActivityTermRequest();

                ActivityTermResponse response = null;
                if (CollectionUtils.isNotEmpty(infoResponse.getActivityTermList())) {
                    response = infoResponse.getActivityTermList().stream()
                            .filter(e -> termRequest.getActivityTermId().equals(e.getActivityTermId()))
                            .findFirst().orElse(null);
                }

                if (Objects.isNull(response)) {
                    //1. 写错误日志
                    log.error("2.未查询到促销活动，参加活动失败，入参 = {}", JSONObject.toJSONString(request));
                    //2. 写错误对象
                    participateActivityInfoResponse.setParticipateResult(false);
                    participateActivityInfoResponse.setParticipateResultMsg("参加活动失败，未查询到促销活动项目！");

                } else {
//                校验通过，继续校验下一个
//                校验通过的结果
                    com.alibaba.citrus.common.Result<Boolean> checkResult = manager.getActivityProcess(infoResponse.getActivityFacadeCode())
                            .checkParticipateActivityData(request, response);
                    participateActivityInfoResponse.setParticipateResult(checkResult.isSuccess());
                    participateActivityInfoResponse.setParticipateResultMsg(checkResult.isSuccess() ? "参加活动参数校验通过!" : checkResult.getMessage());
                }
            }
            lists.add(participateActivityInfoResponse);
        });

        participateInActivityResponse.setParticipateActivityResponseList(lists);

        return participateInActivityResponse;
    }

    /**
     * 参加活动
     *
     * @param request 请求
     * @return
     */
    @Override
    @FacadeInvoker(value = "参加活动", errorCode = "OTS-08-002-01-16-002")
    public Result<ParticipateInActivityResponse> participateActivity(ParticipateActivityRequest request) {
        if (Objects.isNull(request) || CollectionUtils.isEmpty(request.getParticipateActivityInfoList())) {
            log.error("参数不能为空！request={}", request);
            log.error("ActivityWriteServiceImpl#participateActivity_fail");
            throw new FacadeException("OTS-08-002-01-16-001");
        }

        // 查询活动
        String queryParamStr = request.getFeatures().get(ActivityFeatureKeyEnum.ADD_ACTIVITY_QUERY_PARAM.getCode());
        if (StringUtils.isBlank(queryParamStr)) {
            // 查询活动参数为空，不能进行活动
            log.error("ActivityWriteServiceImpl#participateActivity_fail");
            throw new FacadeException("OTS-08-002-01-16-001");
        }
        String redisKey = ACTIVITY_PARTICIPATE + request.getParticipateActivityInfoList().get(0).getSequenceNo();

        try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(), redisKey, TIMEOUT_MSECS, EXPIRE_MSECS)) {
            boolean locked = lock.lock();
            if (!locked) {
                log.error("获取分布式锁失败：ActivityWriteServiceImpl#participateActivity.getLock.fail RedisKey=" + redisKey);
                log.error("ActivityWriteServiceImpl#participateActivity_fail");
                return Result.fail("OTS-08-002-01-16-010", "系统繁忙，请稍后重试!");
            }

            // 根据查询参数查询活动信息
            QueryActivityRequest queryActivityRequest = JSON.parseObject(queryParamStr, QueryActivityRequest.class);
            Result<ActivityResponse> queryActivityResponse = activityQueryServiceImpl.batchQueryCanUsingActivityExpand(queryActivityRequest);
            if (!queryActivityResponse.isSuccess()) {
                // 查询活动失败
                return Result.fail(queryActivityResponse.getErrorCode(), queryActivityResponse.getMessage());
            }

            // 将内部代码转换为外部代码
            if (queryActivityRequest.getFeatures().get(CODE_FLAG).equals(INNER_CODE_TO_OUT_CODE)){
                conversionInnerCode(queryActivityResponse);
            }

            // 校验活动的特殊价格和礼物
            ParticipateInActivityResponse checkResponse = checkSpecialPriceAndGift(request, queryActivityResponse);

            // 校验组合特价
            checkComponentSpecialPrice(request, queryActivityResponse, checkResponse);

            ParticipateInActivityResponse response = new ParticipateInActivityResponse();

            // 更新乐观锁版本
            updateLockVersion(request, queryActivityResponse);

            // 将校验结果转换为特定的格式，以供后续处理
            Map<String, ParticipateActivityInfoResponse> checkResponseMap = convertCheckResponseMap(checkResponse);

            response.setParticipateActivityResponseList(new ArrayList<>());

            // 构建活动信息转换对象列表
            List<ActivityTO> activityTOS = buildActivityTOList(request);

            //批量分组参加活动
            //1.遍历根据活动id(分组管控标识为"X")/活动项目id聚合的TO
            //2.遍历没一个聚合项
            //3.以每一个聚合项为一个整体进行活动的预占，有一个子项失败时，整体置为失败
            //4.对预占成功的进行实际的占用，失败后
            activityTOS.forEach(activityTO -> {
                activityTO.setResult(true);
                Map<ParticipateActivityInfoRequest, ActivityEntity> entityMap = activityTO.getActivityInfoRequestActivityEntityMap();
                List<ParticipateActivityInfoResponse> infoResponseList = Lists.newArrayList();
                Integer quantitySum = 0;
                long feeSum = 0L;
                Map<ParticipateActivityInfoRequest, ParticipateActivityInfoResponse> responseMap = new HashMap<>();
                for (Map.Entry<ParticipateActivityInfoRequest, ActivityEntity> entry : entityMap.entrySet()) {
                    ParticipateActivityInfoRequest activityInfoRequest = entry.getKey();
                    ActivityEntity activityEntity = entry.getValue();

                    //获取校验后的结果
                    ParticipateActivityInfoResponse activityInfoResponse = checkResponseMap.get(activityInfoRequest.getActivityId() + "_"
                            + activityInfoRequest.getParticipateActivityTermRequest().getActivityTermId() + "_" + activityInfoRequest.getSubOrderId());

                    //补全活动类型
                    activityInfoResponse.setActivityType(activityEntity.obtainActivityType());

                    if (activityInfoResponse.getParticipateResult()) {
                        // 校验费用和数量，以及是否重复占用
                        activityInfoResponse = activityEntity.updateActivityQuantityAndFee(activityInfoRequest);

                        Integer thisPreQuantity = activityInfoResponse.getParticipateSuccessItemCount();
                        quantitySum += thisPreQuantity;

                        // 本次预占用费用
                        long thisPreOccupyFee = activityInfoResponse.getParticipateSuccessFee();
                        feeSum += thisPreOccupyFee;
                        if (activityTO.getGroupControlFlag()) {
                            ActivityTermSDO activityTermSDO = activityEntity.getTermEntityList().get(0).getSdo();
                            // 更新活动占用数量和费用
                            activityTermSDO.setActivityOccupyQuantity(thisPreQuantity);
                            activityTermSDO.setActivityOccupyFee(thisPreOccupyFee);
                        }
                    }
                    // 设置相关ID和订单类型
                    activityInfoResponse.setItemId(activityInfoRequest.getParticipateActivityTermRequest().getItem().getItemId());
                    activityInfoResponse.setOrderType(activityInfoRequest.getOrderType());
                    infoResponseList.add(activityInfoResponse);
                    responseMap.put(activityInfoRequest, activityInfoResponse);
                    // 若有任一子项失败，则整体失败
                    if (!activityInfoResponse.getParticipateResult()) {
                        log.error("有一个失败，该活动 term 下的所有参加结果都重置为不成功！参加结果={}", activityInfoResponse);
                        activityTO.setResult(false);
                    }
                }

                // 设置活动占用量和费用总和
                activityTO.setActivityInfoResponseMap(responseMap);
                activityTO.setQuantitySum(quantitySum);
                activityTO.setFeeSum(feeSum);

                // 处理整体失败的情况
                if (!activityTO.getResult()) {
                    infoResponseList.forEach(infoResponse -> {
                        if (infoResponse.getParticipateResult()) {
                            infoResponse.setParticipateResultMsg("该子单参加活动失败!原因：该活动项目下的其他子单活动占用失败，导致该子单失败！");
                            infoResponse.setParticipateResult(false);
                            infoResponse.setParticipateSuccessItemCount(0);
                            infoResponse.setParticipateSuccessFee(0L);
                        }
                    });
                }
                // 添加参加活动的详细响应信息
                response.getParticipateActivityResponseList().addAll(infoResponseList);
            });

            // 过滤掉预占失败的请求
            List<ActivityTO> successActivityTOList = activityTOS.stream().filter(
                    item -> BooleanUtils.isTrue(item.getResult())).collect(Collectors.toList());

            // 校验总预占数量和费用是否符合要求
            successActivityTOList.forEach(activityTO -> {
                Boolean isCanOccupyTermResult = activityTO.isCanOccupy();
                if (!isCanOccupyTermResult) {
                    activityTO.setResult(false);
                    // 置预占失败的详细信息
                    activityTO.getActivityInfoResponseMap().forEach((key, infoResponse) -> {
                        infoResponse.setParticipateResult(false);
                        infoResponse.setParticipateSuccessItemCount(0);
                        infoResponse.setParticipateSuccessFee(0L);
                        String failMsg;
                        if (activityTO.getGroupControlFlag()) {
                            failMsg = "该活动参加活动失败！原因：总的申请数量大于活动便签剩余活动数量 或 总的占用金额大于活动便签剩余金额！活动便签号="
                                    + activityTO.getActivityNoteId();
                        } else {
                            failMsg = "该活动参加活动失败！原因：总的申请数量大于剩余活动数量 或 总的占用金额大于剩余金额！活动 id="
                                    + key.getActivityId() + ",活动项目 id="
                                    + key.getParticipateActivityTermRequest().getActivityTermId();
                        }
                        infoResponse.setParticipateResultMsg(failMsg);
                    });
                }
            });

            //过滤掉预占失败的请求
            successActivityTOList = activityTOS.stream().filter(e -> BooleanUtils.isTrue(e.getResult())).collect(Collectors.toList());

            // 保存预占成功的活动记录
            applicationContext.getBean(ActivityWriteServiceImpl.class).saveActivityRecord(successActivityTOList);
            return Result.success(response);
        } catch (Exception e) {
            log.error("活动占用失败！", e);
        }
        return Result.fail("", "活动占用失败！");
    }

    /**
     * 更新乐观锁版本
     *
     * @param request
     * @param queryActivityResponse
     */
    private void updateLockVersion(ParticipateActivityRequest request, Result<ActivityResponse> queryActivityResponse) {

        //按照 activityId_activityTermId进行分组
        Map<String, List<ParticipateActivityInfoRequest>> participateMap = request.getParticipateActivityInfoList().stream()
                .collect(Collectors.groupingBy(e -> e.getActivityId() + "_" + e.getParticipateActivityTermRequest().getActivityTermId()));


        //按照 activityId_activityTermId进行分组
        Map<String, List<ActivityInfoResponse>> queryMap = Nullable.stream(queryActivityResponse.getResult().getActivityInfoResponseList())
                .collect(Collectors.groupingBy(e -> e.getActivityId() + "_" + e.getActivityTermList().get(0).getActivityTermId()));

        participateMap.entrySet().forEach(entry -> {
            String key = entry.getKey();
            List<ParticipateActivityInfoRequest> participateList = entry.getValue();

            if (CollectionUtils.isNotEmpty(queryMap.get(key))) {
                Integer version = queryMap.get(key).get(0).getActivityTermList().get(0).getVersion();
                Integer activityTitleExtVersion = queryMap.get(key).get(0).getActivityTitleExtVersion();
                participateList.forEach(participate -> {
                    participate.setActivityTitleExtVersion(activityTitleExtVersion);
                    participate.getParticipateActivityTermRequest().setVersion(version);
                });
            } else {
                String[] strs = key.split("_");
                log.error("更新版本号时：未查询到该活动，活动 ID=" + strs[0] + "，活动项目 id=" + strs[1]);
            }

        });
    }

    /**
     * 校验组合特价
     *
     * @param request                     请求
     * @param queryActivityResponseResult 活动校验结果
     * @param checkResponse
     */
    private void checkComponentSpecialPrice(ParticipateActivityRequest request, Result<ActivityResponse> queryActivityResponseResult,
                                            ParticipateInActivityResponse checkResponse) {
//        1. 对请求结果中的活动 termId 对商品进行归堆
//        2. 在查询结果中，获取该 termId下所有货品的组合特价
//        3. 由于子单上商品不允许重复（add by myw,20221104 子单商品允许重复），校验该组合下 termId 下的所有货品的组合特价
//        key： activityId_termId_subOrderId_commonGroupFlag, value: specialPrice
        Map<String, String> participateRequestMap = convertParticipateInfoMap(request);

//        key： activityId_termId_commonGroupFlag, 这里仅获取组合特价的分组，非组合特价的不获取
        Map<String, List<ActivityInfoResponse>> queryActivityResponseMap = convertQueryActivityResponse(queryActivityResponseResult.getResult());

//        参加活动结果的 map, key：activityId_termId_subOrderId，value: 参加活动的返回结果
        Map<String, ParticipateActivityInfoResponse> participateResponseMap = convertParticipateResponseMap(checkResponse.getParticipateActivityResponseList());

        //无组合特价直接返回
        if (MapUtils.isEmpty(queryActivityResponseMap) || MapUtils.isEmpty(participateRequestMap)) {
            return;
        }

        log.info("打印下queryActivityResponseMap参数：" + JSON.toJSONString(queryActivityResponseMap));
        //对同一个term 下所有组合特价信息进行校验
        for (Map.Entry<String, List<ActivityInfoResponse>> entry : queryActivityResponseMap.entrySet()) {
//            key:activityId_termId_subOrderId_commonGroupFlag, value: specialPrice
            Map<String, String> infoResponseMap = convertQueryInfoResponse(entry.getValue());

            boolean isMatch = true;
            for (Map.Entry<String, String> en : infoResponseMap.entrySet()) {
                String key = en.getKey();
                String specialPrice = en.getValue();
                String[] strs = key.split("_");
                String newKey = strs[0] + "_" + strs[1] + "_" + strs[2];
                ParticipateActivityInfoResponse response = participateResponseMap.get(newKey);
                if (!specialPrice.equals(participateRequestMap.get(key))) {
                    if (response == null) {
                        isMatch = false;
                        continue;
                    }
                } else {
                    //说明相等，但是有前面的不匹配，当前活动参加失败
                    if (!isMatch) {
                        response.setParticipateResult(false);
                        response.setParticipateResultMsg("组合特价校验不过，子单 ID=" + strs[2] + "活动 id=" + strs[0] + ",活动项目 id=" + strs[1]);
                        response.setParticipateSuccessItemCount(0);
                        response.setParticipateSuccessFee(0L);
                    }
                }
            }
        }
    }

    /**
     * key：activityId_termId_itemId，value: 参加活动的返回结果
     *
     * @param participateActivityResponseList 参加下活动列表
     * @return key：activityId_termId_subOrderId，value: 参加活动的返回结果 response:ParticipateActivityInfoResponse
     */
    private Map<String, ParticipateActivityInfoResponse> convertParticipateResponseMap(List<ParticipateActivityInfoResponse> participateActivityResponseList) {
        return participateActivityResponseList.stream().collect(
                Collectors.toMap(e -> e.getActivityId() + "_" + e.getActivityTermId() + "_" + e.getSubOrderId(), Function.identity()));
    }

    /**
     * 转换查询结果
     *
     * @param activityInfoResponseList 活动信息结果列表
     * @return
     */
    private Map<String, String> convertQueryInfoResponse(List<ActivityInfoResponse> activityInfoResponseList) {
//        activityId_termId_subOrderId_commonGroupFlag
        return activityInfoResponseList.stream().collect(Collectors.toMap(e -> {
            ActivityTermResponse termResponse = e.getActivityTermList().get(0);
            return e.getActivityId() + "_" + termResponse.getActivityTermId() + "_" + e.getSubOrderId()
                    + "_" + termResponse.getCommonGroupFlag();

        }, e -> {
            return e.getActivityTermList().get(0).getSpecialOfferPrice();
        }));
    }

    /**
     * 转换查询活动校验结果
     *
     * @param result 结果
     * @return key：activityId_termId_commonGroupFlag  value:List<ActivityInfoResponse>
     */
    private Map<String, List<ActivityInfoResponse>> convertQueryActivityResponse(ActivityResponse result) {
        return Nullable.stream(result.getActivityInfoResponseList())
                .filter(info -> StringUtils.isNotBlank(info.getActivityTermList().get(0).getCommonGroupFlag()))
                .collect(Collectors.groupingBy(info -> info.getActivityId() + "_" + info.getActivityTermList().get(0).getActivityTermId() + "_"
                        + info.getActivityTermList().get(0).getCommonGroupFlag()));

    }

    /**
     * key： activityId_termId_subOrderId_commonGroupFlag, value: specialPrice
     *
     * @param request
     * @return
     */
    private Map<String, String> convertParticipateInfoMap(ParticipateActivityRequest request) {
        Map<String, String> map = new HashMap<>();
        if (CollectionUtils.isEmpty(request.getParticipateActivityInfoList())) {
            return map;
        }

        request.getParticipateActivityInfoList().forEach(info -> {
            String commonGroupFlag = info.getParticipateActivityTermRequest().getCommonGroupFlag();
            if (StringUtils.isNotBlank(commonGroupFlag)) {
                String key = info.getActivityId() + "_" + info.getParticipateActivityTermRequest().getActivityTermId()
                        + "_" + info.getSubOrderId() + "_" + commonGroupFlag;
                map.putIfAbsent(key, info.getParticipateActivityTermRequest().getSpecialOfferPrice().toString());
            }
        });

        return map;
    }

    /**
     * 查询活动时的货品内外码转换
     *
     * @param activityResponseResult
     */
    private void conversionInnerCode(Result<ActivityResponse> activityResponseResult) {
        List<String> itemIds = Lists.newArrayList();
        List<ActivityInfoResponse> activityInfoResponseList = activityResponseResult.getResult().getActivityInfoResponseList();
        if (CollectionUtils.isEmpty(activityInfoResponseList)) {
            log.error("未查询到可用活动 = {}", activityResponseResult);
            return;
        }
        activityInfoResponseList.forEach(e -> {
            e.getActivityTermList().forEach(term -> {
                String itemId = term.getItemId();
                if (StringUtils.isNotBlank(itemId)) {
                    itemIds.add(itemId);
                }
                List<ActivityItemInfo> giftList = term.getGiftList();
                if (CollectionUtils.isNotEmpty(giftList)) {
                    giftList.stream().forEach(gift -> {
                        String giftId = gift.getItemId();
                        if (StringUtils.isNotBlank(giftId)) {
                            itemIds.add(giftId);
                        }
                    });
                }
            });
        });

        Map<String, String> itemCodeMap = propertyProcessManager.
                getPropertyProcess(DimensionPropertyEnum.MATERIAL_CODE.getKey()).
                obtainInnerCodeAndOuterCodeMap(itemIds, true);
        activityResponseResult.getResult().getActivityInfoResponseList().forEach(e -> {
            e.getActivityTermList().forEach(term -> {
                String itemId = term.getItemId();
                if (StringUtils.isNotBlank(itemId)) {
                    term.setItemId(itemCodeMap.get(itemId));
                }
                List<ActivityItemInfo> giftList = term.getGiftList();
                if (CollectionUtils.isNotEmpty(giftList)) {
                    giftList.stream().forEach(gift -> {
                        String giftId = gift.getItemId();
                        if (StringUtils.isNotBlank(giftId)) {
                            gift.setItemId(itemCodeMap.get(giftId));
                        }
                    });
                }
            });
        });

    }

    /**
     * 转换成 map
     *
     * @param checkResponse 校验结果
     * @return 转换成 map， key: activityId_termId_subOrderId; value: ParticipateActivityInfoResponse
     */
    private Map<String, ParticipateActivityInfoResponse> convertCheckResponseMap(ParticipateInActivityResponse checkResponse) {
        return checkResponse.getParticipateActivityResponseList().stream().collect(Collectors.toMap(
                e -> e.getActivityId() + "_" + e.getActivityTermId() + "_" + e.getSubOrderId(), Function.identity()));
    }

    /**
     * 参加活动的更新到数据库里
     *
     * @param successActivityTOList
     * @return
     */
    @EpochTransactional(appCode="cr_forecast_sales", dataSourceCode = "cr_ots", dataSourceType = "app")
    @ProcessInvoker
    public Boolean saveActivityRecord(List<ActivityTO> successActivityTOList) {

        successActivityTOList.forEach(activityTO -> {

            Map<ParticipateActivityInfoRequest, ParticipateActivityInfoResponse> responseMap = activityTO.getActivityInfoResponseMap();
            Map<ParticipateActivityInfoRequest, ActivityEntity> entityMap = activityTO.getActivityInfoRequestActivityEntityMap();
                ParticipateActivityInfoRequest key = entityMap.keySet().stream().findFirst().orElse(null);
            ActivityEntity activityEntity = entityMap.get(key);
            //取第一个更新term表数据
            ActivityTermEntity termEntity = activityEntity.getTermEntityList().get(0);
            ActivityTitleExtEntity titleExtEntity = activityEntity.getTitleExtEntity();
            Boolean updateResult = false;
            if (!activityTO.getGroupControlFlag()) {
                //刷新占用数量和占用金额
                termEntity.flushOccupyQuantityAndFee(activityTO.getQuantitySum(), activityTO.getFeeSum(), key.getParticipateActivityTermRequest().getVersion());
                updateResult = activityEntity.saveActivityTerm();
            } else {

                //更新活动抬头扩展表占用量和占用金额以及每条term表数据
                titleExtEntity.flushOccupyQuantityAndFee(activityTO.getQuantitySum(), activityTO.getFeeSum(), key.getActivityTitleExtVersion());
                updateResult = activityEntity.saveActivityTitleExt();
                if (updateResult) {
                    //1.根据活动项目号进行聚合
                    //2.获取每个子单活动占用的增量（活动占用量和占用费用）
                    //3.统一更新
                    Map<String, List<ParticipateActivityInfoRequest>> participateActivityMap = entityMap.keySet().stream().collect(Collectors.groupingBy(e -> e.getParticipateActivityTermRequest().getActivityTermId()));
                    Set<String> activityTermIds = participateActivityMap.keySet();
                    //获取活动项目号和活动项目的对应关系
                    List<ActivityTerm> activityTerms = activityQueryRepository.queryActivityIdsByActivityTermIds(Lists.newArrayList(activityTermIds));
                    if (Objects.isNull(activityTerms)) {
                        log.error("未查询到活动项目：" + activityTerms);
                        throw new ProcessException("OTS-08-002-01-16-014");
                    }
                    Map<String, ActivityTerm> activityTermMap = activityTerms.stream().collect(Collectors.toMap(ActivityTerm::getActivityTermId, Function.identity(), (x, y) -> x));

                    for (String activityTermId : participateActivityMap.keySet()) {
                        List<ParticipateActivityInfoRequest> participateActivityInfoRequests = participateActivityMap.get(activityTermId);
                        ActivityTerm activityTerm = activityTermMap.get(activityTermId);
                        if (Objects.isNull(activityTerm)) {
                            log.error("未查询到活动项目：" + activityTermId);
                            throw new ProcessException("OTS-08-002-01-16-014");
                        }
                        Integer originOccupyQuantity = activityTerm.getActivityOccupyQuantity();
                        Long originOccupyFee = activityTerm.getActivityOccupyFee();
                        Integer newOccupyQuantity = originOccupyQuantity;
                        Long newOccupyFee = originOccupyFee;

                        ActivityTermEntity activityTermEntity = null;
                        for (ParticipateActivityInfoRequest e : participateActivityInfoRequests) {
                            if (Objects.isNull(activityTermEntity)) {
                                activityTermEntity = entityMap.get(e).getTermEntityList().get(0);
                            }
                            ActivityTermEntity subActivityTermEntity = entityMap.get(e).getTermEntityList().get(0);
                            newOccupyQuantity += subActivityTermEntity.obtainActivityOccupyQuantity() ;
                            newOccupyFee += subActivityTermEntity.obtainActivityOccupyFee();
                        }

                        //更新同一个term
                        activityTermEntity.setActivityOccupyQuantity(newOccupyQuantity);
                        activityTermEntity.setActivityOccupyFee(newOccupyFee);

                        updateResult = activityTermEntity.save();
                        if (!updateResult) {
                            break;
                        }
                    }
                }

            }

            //保存
            if (!updateResult) {
                //活动总占用失败时，将之前以子单维度批量占用成功的结果全部置为失败
                activityTO.getActivityInfoResponseMap().entrySet().forEach(entry -> {
                    String resultMsg = "参加活动失败！原因：term保存更新失败，该 term 下所有子单更新为失败！活动 Id="
                            + entry.getKey().getActivityId() + ",活动项目 id=" + entry.getKey().getParticipateActivityTermRequest().getActivityTermId();
                    ParticipateActivityInfoResponse infoResponse = entry.getValue();
                    infoResponse.setParticipateResult(false);
                    infoResponse.setParticipateResultMsg(resultMsg);
                    log.warn("Activity use failed: " + resultMsg);
                });
                // TBD 这里需要阻断确认流程，批量不能阻断，一个主单可以阴断？
                log.warn("Activity use failed: " + "Concurrent version occupy failed: " + JSON.toJSONString(activityTO));

            } else {
                //测试活动占用事务处理，todo qjg 上线前要进行删除
                //long temp = 10 / CrPriceCenterConstants.TRANSACTIONAL_PARTICIPATE_ACTIVITY_TEST();

                //保存参加活动记录数据
                responseMap.entrySet().forEach(entry -> {
                    ParticipateActivityInfoRequest infoRequest = entry.getKey();
                    ActivityEntity tempEntity = entityMap.get(infoRequest);
                    ParticipateActivityInfoResponse infoResponse = entry.getValue();
                    tempEntity.saveActivityUseRecord(infoRequest, infoResponse,activityTO.getGroupControlFlag());
                });
            }
        });
        return true;
    }


    /**
     * 构建活动 TO列表
     *
     * @param request
     * @return
     */
    @FacadeInvoker
    private List<ActivityTO> buildActivityTOList(ParticipateActivityRequest request) {
        List<ActivityTO> activityTOList = new ArrayList<>();

        //查询受分组管控的活动
        Set<String> activityIds = request.getParticipateActivityInfoList().stream().map(e -> e.getActivityId()).collect(Collectors.toSet());
        List<ActivityTitle> activityTitles = activityQueryRepository.queryGroupControlActivityIdAndNoteId(activityIds);
        //受分组管控的活动号
        List<String> groupControlActivityIds = activityTitles.stream().map(ActivityTitle::getActivityId).collect(Collectors.toList());
        //受分组管控的活动号和活动便签号的对应关系
        Map<String, String> activityIdAndActivityNoteIdMap = activityTitles.stream().collect(Collectors.toMap(ActivityTitle::getActivityId, ActivityTitle::getActivityNoteId));
        //分组管控活动入参
        List<ParticipateActivityInfoRequest> groupControlActivityRequestList = request.getParticipateActivityInfoList().stream().filter(e -> groupControlActivityIds.contains(e.getActivityId())).collect(Collectors.toList());
        groupControlActivityRequestList.forEach(e -> e.setActivityNoteId(activityIdAndActivityNoteIdMap.get(e.getActivityId())));

        //非分组管控活动入参
        List<ParticipateActivityInfoRequest> notGroupControlActivityRequestList = request.getParticipateActivityInfoList().stream().filter(e -> !groupControlActivityIds.contains(e.getActivityId())).collect(Collectors.toList());

        // 获取来源系统，用来区分活动校验逻辑
        String source = "";
        if (MapUtils.isNotEmpty(request.getFeatures())) {
            source = request.getFeatures().get("os");
        }

        //根据活动 ID 进行归堆
        //不受分组管控的根据activityId+activityTermId进行归堆
        Map<String, List<ParticipateActivityInfoRequest>> notGroupControlRequestMap = notGroupControlActivityRequestList.stream().collect(Collectors.groupingBy(x -> x.getActivityId()));
        for (String activityId : notGroupControlRequestMap.keySet()) {
            //活动号+活动项目号和request的对应关系
            Map<String, List<ParticipateActivityInfoRequest>> map = new HashMap<>();
            List<ParticipateActivityInfoRequest> participateActivityInfoRequests = notGroupControlRequestMap.get(activityId);
            //根据活动 termId 进行归堆
            Map<String, List<ParticipateActivityInfoRequest>> subMap = participateActivityInfoRequests.stream().collect(Collectors.groupingBy(y ->
                    y.getParticipateActivityTermRequest().getActivityTermId()
            ));
//            subMap.keySet().forEach(termId -> map.put(activityId + "_" + termId, subMap.get(termId)));

            for (Map.Entry<String, List<ParticipateActivityInfoRequest>> entry : subMap.entrySet()) {
                String termId = entry.getKey();
                String key = activityId + "_" + termId;
                List<ParticipateActivityInfoRequest> infoRequestList = map.get(key);
                if (CollectionUtils.isEmpty(infoRequestList)) {
                    map.put(key, subMap.get(termId));
                } else {
                    infoRequestList.addAll(subMap.get(termId));
                }
            }

            for (String activityIdAndTermId : map.keySet()) {
                ActivityTO activityTO = new ActivityTO();
                Map<ParticipateActivityInfoRequest, ActivityEntity> entityMap = Maps.newHashMap();
                String[] key = activityIdAndTermId.split("_");
                activityTO.setActivityId(key[0]);
                activityTO.setActivityTermId(key[1]);
                for (ParticipateActivityInfoRequest activityInfo : map.get(activityIdAndTermId)) {
                    ActivityEntity activityEntity = ActivityFactory.create(activityInfo);
                    entityMap.put(activityInfo, activityEntity);
                }
                activityTO.setActivityInfoRequestActivityEntityMap(entityMap);
                activityTO.setGroupControlFlag(false);
                activityTO.setFeeSum(0L);
                activityTO.setQuantitySum(0);

                activityTOList.add(activityTO);
            }
        }

        //受分组管控的根据活动便签号进行聚合
        Map<String, List<ParticipateActivityInfoRequest>> groupControlRequestMap = groupControlActivityRequestList.stream().collect(Collectors.groupingBy(e -> e.getActivityNoteId()));
        for (String activityNoteId : groupControlRequestMap.keySet()) {
            List<ParticipateActivityInfoRequest> participateActivityInfoRequests = groupControlRequestMap.get(activityNoteId);
            ActivityTO activityTO = new ActivityTO();
            activityTO.setGroupControlFlag(true);
            activityTO.setFeeSum(0L);
            activityTO.setQuantitySum(0);
            activityTO.setActivityNoteId(activityNoteId);
            activityTO.setSource(source);
            Map<ParticipateActivityInfoRequest, ActivityEntity> entityMap = Maps.newHashMap();
            activityTO.setActivityInfoRequestActivityEntityMap(entityMap);

            participateActivityInfoRequests.forEach(activityInfo -> {
                ActivityEntity activityEntity = ActivityFactory.create(activityInfo);
                entityMap.put(activityInfo, activityEntity);
            });
            activityTOList.add(activityTO);

        }
        log.info("活动归堆后的数据 activityTOList={}", JSON.toJSONString(activityTOList));

        return activityTOList;
    }


    /**
     * 活动回补_包含转码功能的接口
     *
     * @param coverActivityRequest
     * @return
     */
    @Override
    @FacadeInvoker(value = "活动回补", errorCode = "OTS-08-002-01-16-003")
    public Result<CoverInActivityResponse> activityCoverExpand(CoverActivityRequest coverActivityRequest) {

        CoverActivityRequest newCoverActivityRequest = new CoverActivityRequest();
        copyValueForActivityCover(coverActivityRequest,newCoverActivityRequest);


        //校验下参数
        if (Objects.isNull(newCoverActivityRequest) || MapUtils.isEmpty(newCoverActivityRequest.getFeatures()) ||
                StringUtils.isBlank(newCoverActivityRequest.getFeatures().get("codeFlag"))) {
            log.error("请传编码转换标识，内部转外部:inner_code_to_out_code,外部转内部:out_code_to_inner_code = {}",
                    JSONObject.toJSONString(newCoverActivityRequest));
            log.error("ActivityWriteServiceImpl#activityCoverExpand_fail");
            throw new FacadeException("OTS-08-001-01-16-018");
        }

        if (PlatformCodeFlagEnum.OUT_CODE_TO_INNER_CODE.getCode().equals(newCoverActivityRequest.getFeatures().get("codeFlag"))) {
            return activityCover(newCoverActivityRequest);
        }

        if (!PlatformCodeFlagEnum.INNER_CODE_TO_OUT_CODE.getCode().equals(newCoverActivityRequest.getFeatures().get("codeFlag"))) {
            log.error("请传正确的编码转换标识，内部转外部:inner_code_to_out_code,外部转内部:out_code_to_inner_code = {}",
                    JSONObject.toJSONString(newCoverActivityRequest));
            log.error("ActivityWriteServiceImpl#activityCoverExpand_fail");
            throw new FacadeException("OTS-08-001-01-16-019");
        }

        //获取所有的内外部编码映射关系
        Set<String> itemOutCodeList = Sets.newHashSet();
        newCoverActivityRequest.getCoverActivityInfoList().stream().forEach(item -> {
            CoverActivityTermRequest coverActivityTermRequest = item.getCoverActivityTermRequest();
            ActivityItemInfo activityItemInfo = coverActivityTermRequest.getItem();
            String itemId = activityItemInfo.getItemId();
            if (StringUtils.isBlank(itemId)) {
                log.error("物料编码不允许为空 = {}", JSONObject.toJSONString(coverActivityTermRequest));
                log.error("ActivityWriteServiceImpl#activityCoverExpand_fail");
                throw new FacadeException("OTS-08-001-01-16-020");
            }
            itemOutCodeList.add(activityItemInfo.getItemId());
            List<ActivityItemInfo> giftList = coverActivityTermRequest.getGiftList();
            if (CollectionUtils.isNotEmpty(giftList)) {
                List<String> giftItemIds = giftList.stream().map(ActivityItemInfo::getItemId).
                        collect(Collectors.toList());
                itemOutCodeList.addAll(giftItemIds);
            }

        });
        Map<String, ScItemSDO> itemMap = activityQueryServiceImpl.obtainItemMap(new ArrayList<>(itemOutCodeList), true);
        log.info("ActivityWriteServiceImpl#activityCoverExpand itemMap:{}", JSONObject.toJSONString(itemMap));
        if (MapUtils.isEmpty(itemMap)) {
            log.error("未查询到货品外部编码，请排查是否存在映射关系 = {}", JSONObject.toJSONString(newCoverActivityRequest));
            log.error("ActivityWriteServiceImpl#activityCoverExpand_fail");
            throw new FacadeException("OTS-08-001-01-16-021");
        }
        log.info("ActivityWriteServiceImpl#activityCoverExpand newCoverActivityRequest:{}", JSONObject.toJSONString(newCoverActivityRequest));
        //参数转换内部编码转外部编码
        List<CoverActivityInfoRequest> coverActivityInfoRequests = newCoverActivityRequest.
                getCoverActivityInfoList().stream().map(coverActivityInfoRequest -> {
                    CoverActivityInfoRequest coverActivityInfoRequestItem = new CoverActivityInfoRequest();
                    BeanUtils.copyProperties(coverActivityInfoRequest, coverActivityInfoRequestItem);
                    CoverActivityTermRequest coverActivityTermRequest = coverActivityInfoRequest.getCoverActivityTermRequest();
                    CoverActivityTermRequest coverActivityTermRequestItem = new CoverActivityTermRequest();
                    BeanUtils.copyProperties(coverActivityTermRequest, coverActivityTermRequestItem);
                    ActivityItemInfo activityItemInfo = coverActivityTermRequest.getItem();
                    ScItemSDO scItemSDO = itemMap.get(activityItemInfo.getItemId());
                    if (Objects.isNull(scItemSDO) || StringUtils.isBlank(scItemSDO.getOuterId())) {
                        log.error("未查询到货品外部编码，请排查是否存在映射关系 = {}", JSONObject.toJSONString(scItemSDO));
                        log.error("ActivityWriteServiceImpl#activityCoverExpand_fail");
                        throw new FacadeException("OTS-08-001-01-16-021");
                    }
                    activityItemInfo.setItemId(scItemSDO.getOuterId());
                    coverActivityTermRequestItem.setItem(activityItemInfo);
                    List<ActivityItemInfo> giftList = coverActivityTermRequest.getGiftList();
                    if (CollectionUtils.isNotEmpty(giftList)) {
                        List<ActivityItemInfo> activityGiftInfos = giftList.stream().map(itemInfo -> {
                            ActivityItemInfo info = new ActivityItemInfo();
                            BeanUtils.copyProperties(itemInfo, info);
                            ScItemSDO scItemInfoSDO = itemMap.get(itemInfo.getItemId());
                            if (Objects.isNull(scItemInfoSDO) || StringUtils.isBlank(scItemInfoSDO.getOuterId())) {
                                log.error("未查询到货品外部编码，请排查是否存在映射关系 = {}", JSONObject.toJSONString(scItemInfoSDO));
                                log.error("ActivityWriteServiceImpl#activityCoverExpand_fail");
                                throw new FacadeException("OTS-08-001-01-16-021");
                            }
                            info.setItemId(scItemInfoSDO.getOuterId());
                            return info;
                        }).collect(Collectors.toList());
                        coverActivityTermRequestItem.setGiftList(activityGiftInfos);
                    }

                    coverActivityInfoRequestItem.setCoverActivityTermRequest(coverActivityTermRequestItem);

                    return coverActivityInfoRequestItem;
                }).collect(Collectors.toList());
        newCoverActivityRequest.setCoverActivityInfoList(coverActivityInfoRequests);

        Result<CoverInActivityResponse> result = applicationContext.getBean(ActivityWriteServiceImpl.class).activityCover(newCoverActivityRequest);

        //外部转回内部
        if (Objects.isNull(result.getResult()) || CollectionUtils.isEmpty(result.getResult().getCoverActivityResponseList())) {
            return new Result<>();
        }

        List<String> outCodeItemIds = new ArrayList<>(result.getResult().getCoverActivityResponseList().stream().
                map(item -> item.getItemId()).collect(Collectors.toSet()));

        //获取外部编码和货品的对应关系
        Map<String, ScItemSDO> outCodeItemMap = activityQueryServiceImpl.obtainItemMap(outCodeItemIds, false);
        CoverInActivityResponse coverInActivityResponse = result.getResult();

        List<CoverActivityInfoResponse> coverActivityInfoResponses = coverInActivityResponse.getCoverActivityResponseList().
                stream().map(item -> {
                    CoverActivityInfoResponse coverActivityInfoResponse = new CoverActivityInfoResponse();
                    BeanUtils.copyProperties(item, coverActivityInfoResponse);
                    ScItemSDO scItemSDO = outCodeItemMap.get(item.getItemId());
                    coverActivityInfoResponse.setItemId("未查询到物料内部编码,请排查是否存在映射关系:" + item.getItemId());
                    if (Objects.nonNull(scItemSDO) && StringUtils.isNotBlank(scItemSDO.getScItemId())) {
                        coverActivityInfoResponse.setItemId(scItemSDO.getScItemId());
                    }
                    return coverActivityInfoResponse;
                }).collect(Collectors.toList());
        coverInActivityResponse.setCoverActivityResponseList(coverActivityInfoResponses);

        return result;
    }


    private void copyValueForActivityCover(CoverActivityRequest oldValue, CoverActivityRequest newValue) {
        newValue.setFeatures(oldValue.getFeatures());

        List<CoverActivityInfoRequest> newCoverActivityInfoRequest = oldValue.getCoverActivityInfoList().stream().map(item -> {
                    CoverActivityInfoRequest coverActivityInfoRequest = new CoverActivityInfoRequest();
                    coverActivityInfoRequest.setActivityId(item.getActivityId());
                    coverActivityInfoRequest.setActivityUseTime(item.getActivityUseTime());
                    coverActivityInfoRequest.setMainOrderId(item.getMainOrderId());
                    coverActivityInfoRequest.setSubOrderId(item.getSubOrderId());
                    coverActivityInfoRequest.setClientId(item.getClientId());
                    coverActivityInfoRequest.setDeliveryDate(item.getDeliveryDate());
                    coverActivityInfoRequest.setOrderType(item.getOrderType());
                    coverActivityInfoRequest.setSequenceNo(item.getSequenceNo());


                    CoverActivityTermRequest newTermRequest = new CoverActivityTermRequest();
                    CoverActivityTermRequest oldTermRequest = item.getCoverActivityTermRequest();
                    newTermRequest.setActivityTermId(oldTermRequest.getActivityTermId());
                    newTermRequest.setVersion(oldTermRequest.getVersion());
                    newTermRequest.setSpecialOfferPrice(oldTermRequest.getSpecialOfferPrice());


                    ActivityItemInfo oldItem = oldTermRequest.getItem();
                    ActivityItemInfo newItem = new ActivityItemInfo();
                    newItem.setActivityOccupyFee(oldItem.getActivityOccupyFee());
                    newItem.setItemName(oldItem.getItemName());
                    newItem.setItemId(oldItem.getItemId());
                    newItem.setItemQuantity(oldItem.getItemQuantity());
                    newItem.setItemPrice(oldItem.getItemPrice());
                    newItem.setStockUnit(oldItem.getStockUnit());
                    newItem.setConversionUnit(oldItem.getConversionUnit());
                    newItem.setSalesUnit(oldItem.getSalesUnit());
                    newTermRequest.setItem(newItem);


                    List<ActivityItemInfo> oldGiftList = oldTermRequest.getGiftList();
                    if (CollectionUtils.isNotEmpty(oldGiftList)) {
                        List<ActivityItemInfo> newGiftList = oldGiftList.stream().map(gift -> {
                            ActivityItemInfo newGift = new ActivityItemInfo();
                            newGift.setActivityOccupyFee(gift.getActivityOccupyFee());
                            newGift.setItemName(gift.getItemName());
                            newGift.setItemId(gift.getItemId());
                            newGift.setItemQuantity(gift.getItemQuantity());
                            newGift.setItemPrice(gift.getItemPrice());
                            newGift.setStockUnit(gift.getStockUnit());
                            newGift.setConversionUnit(gift.getConversionUnit());
                            newGift.setSalesUnit(gift.getSalesUnit());
                            return newGift;
                        }).collect(Collectors.toList());

                        newTermRequest.setGiftList(newGiftList);
                    }

                    coverActivityInfoRequest.setCoverActivityTermRequest(newTermRequest);

                    return coverActivityInfoRequest;
                }
        ).collect(Collectors.toList());
        newValue.setCoverActivityInfoList(newCoverActivityInfoRequest);
    }





    /**
     * 活动回补
     *
     * @param request 请求
     * @return
     */
    @Override
    @ProcessInvoker(value = "活动回补", errorCode = "OTS-08-002-01-16-003")
    public Result<CoverInActivityResponse> activityCover(CoverActivityRequest request) {

        CoverInActivityResponse response = new CoverInActivityResponse();
        response.setCoverActivityResponseList(new ArrayList<>());

        //2. 执行扣减活动占用量和活动占用金额
        for (CoverActivityInfoRequest activityInfo : request.getCoverActivityInfoList()) {

            //校验下参数
            checkActivity(activityInfo);

            String redisKey = buildActivityCoverKey(activityInfo);
            try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(), redisKey, TIMEOUT_MSECS, EXPIRE_MSECS)) {
                boolean locked = lock.lock();
                if (!locked) {
                    log.error("获取分布式锁失败：ActivityWriteServiceImpl#activityCover.getLock.fail RedisKey=" + redisKey);
                    log.error("ActivityWriteServiceImpl#activityCover_fail");
                    return Result.fail("OTS-08-002-01-16-011", "系统繁忙，请稍后重试!");
                }
                log.info("activity rollback redis lock key:"+redisKey);

                ParticipateActivityInfoRequest participateActivityInfoRequest = new ParticipateActivityInfoRequest();
                BeanUtils.copyProperties(activityInfo, participateActivityInfoRequest);

                ParticipateActivityTermRequest participateActivityTermRequest = new ParticipateActivityTermRequest();
                BeanUtils.copyProperties(activityInfo.getCoverActivityTermRequest(), participateActivityTermRequest);

                participateActivityInfoRequest.setParticipateActivityTermRequest(participateActivityTermRequest);
                ActivityEntity activityEntity = ActivityFactory.create(participateActivityInfoRequest);

                //正常的更新数据库
                activityReverseDB(response, activityInfo, activityEntity);
            } catch (Exception e) {
                log.error("ActivityWriteServiceImpl#activityCover_fail");
                log.error("活动回补失败！！！", e);
            }
        }
        boolean allSuccess = !response.getCoverActivityResponseList().stream().allMatch(CoverActivityInfoResponse::getCoverResult);
        if (allSuccess){
           return Result.fail(response,"OTS-08-002-01-16-003","活动回补失败!");
        }

        return Result.success(response);

    }

    /**
     * 活动回补，这是真正的更新 DB
     * @param response
     * @param activityInfo
     * @param activityEntity
     */
//    @EpochTransactional(appCode="cr_forecast_sales", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void activityReverseDB(CoverInActivityResponse response, CoverActivityInfoRequest activityInfo, ActivityEntity activityEntity) {
        //初始化线程变量
        ActivitySaveFlagThreadLocal.set(false);
        //3. 更新活动数量和费用
        CoverActivityInfoResponse coverActivityInfoResponse = activityEntity.updateActivityQuantityAndFeeForCover(activityInfo);
        response.getCoverActivityResponseList().add(coverActivityInfoResponse);

        //4. 回补成功，就进行保存
        if (coverActivityInfoResponse.getCoverResult()) {
            Boolean cover = activityEntity.cover();
            coverActivityInfoResponse.setCoverResultMsg(cover ? "回补成功" : "回补失败");
            coverActivityInfoResponse.setCoverResult(cover);
        }
        ActivitySaveFlagThreadLocal.clear();
    }

    @NotNull
    private ThreadLocal<Boolean> getBooleanThreadLocal() {
        ThreadLocal<Boolean> threadLocal = new ThreadLocal<>();
        threadLocal.set(Boolean.FALSE);
        return threadLocal;
    }

    /**
     * 构建活动回补 redis key
     *
     * @param activityInfo 活动信息
     * @return redis Key
     */
    private String buildActivityCoverKey(CoverActivityInfoRequest activityInfo) {
        return ACTIVITY_COVER +activityInfo.getActivityId() + "_" + activityInfo.getCoverActivityTermRequest().getActivityTermId() + "_" +
                activityInfo.getMainOrderId() + "_" + activityInfo.getSubOrderId() + "_" + activityInfo.getSequenceNo();
    }

    /**
     * 校验活动参数
     *
     * @param checkRequest
     */
    private void checkActivityParam(ParticipateActivityRequest checkRequest) {
        if (Objects.isNull(checkRequest)) {
            throw new FacadeException("OTS-08-001-01-16-032");
        }

        if (CollectionUtils.isEmpty(checkRequest.getParticipateActivityInfoList())) {
            throw new FacadeException("OTS-08-001-01-16-033");
        }

        if (checkRequest.getParticipateActivityInfoList().size() > 50) {
            throw new FacadeException("OTS-08-001-01-16-034");
        }

        checkRequest.getParticipateActivityInfoList().forEach(activityInfo -> {
            checkActivityInfoParam(activityInfo);
        });

    }

    private void checkActivityInfoParam(ParticipateActivityInfoRequest activityInfo) {
        /**
         * 客户 id
         */
        if (StringUtils.isBlank(activityInfo.getClientId())) {
            throw new FacadeException("OTS-08-001-01-16-009");
        }
        /**
         * 订单 ID
         */
        if (StringUtils.isBlank(activityInfo.getMainOrderId())) {
            throw new FacadeException("OTS-08-001-01-16-010");
        }
        /**
         * 子单 ID
         */
        if (StringUtils.isBlank(activityInfo.getSubOrderId())) {
            throw new FacadeException("OTS-08-001-01-16-011");
        }
        /**
         * 活动 id
         */
        if (StringUtils.isBlank(activityInfo.getActivityId())) {
            throw new FacadeException("OTS-08-001-01-16-012");
        }
        /**
         * 校验活动列表,当前应该只有一个活动项目，正常这里只能存放一个
         */
        if (Objects.isNull(activityInfo.getParticipateActivityTermRequest())) {
            throw new FacadeException("OTS-08-001-01-16-013");
        }
        /**
         * 交货日期
         */
        if (Objects.isNull(activityInfo.getDeliveryDate())) {
            throw new FacadeException("OTS-08-001-01-16-014");
        }
        /**
         * 活动使用日期
         */
        if (Objects.isNull(activityInfo.getActivityUseTime())) {
            throw new FacadeException("OTS-08-001-01-16-015");
        }
    }


    /**
     * 根据销售订单状态进行活动回退参数拼接
     */
    @Override
    @FacadeInvoker // TBD 消息是否可以重投？
    public Result<Boolean> backOffActivity(BackOffActivityRequest request) {

        log.info("BackOffActivityRequest  request 活动回退入参:}" + JSONObject.toJSONString(request));

        if (Objects.isNull(request) || StringUtils.isEmpty(request.getMessage())) {
            // FIXME 这里返回失败，会重投消息
            return Result.fail("888", "消息为空");
        }
        TradeMessageSDO tradeMessageSDO = JSONObject.parseObject(request.getMessage(), TradeMessageSDO.class);
        OrderSDO orderSDO = tradeMessageSDO.getOrderSDO();
        List<String> affectLineIds = tradeMessageSDO.getAffectLineIds();

        if (Objects.isNull(orderSDO)) {
            log.error("orderSDO为空，tradeMessageSDO = {}", tradeMessageSDO);
            return Result.fail("888", "orderSDO为空");
        }

        if (CollectionUtils.isEmpty(affectLineIds)) {
            return Result.fail("888", "被拒绝的子单行为空");
        }


        if (CollectionUtils.isEmpty(orderSDO.getOrderLineSDOS())) {
            return Result.fail("888", "销售订单子单不能为空");

        }
        List<OrderLineSDO> orderLineSDOList = new ArrayList<>();


        List<CoverActivityInfoRequest> coverActivityInfoRequests = new ArrayList<>();

        for (OrderLineSDO orderLineSDO : orderSDO.getOrderLineSDOS()) {
            if (StringUtils.isNotBlank(orderLineSDO.getActivityCode())) {
                orderLineSDOList.add(orderLineSDO);
            }
        }

        //如果拒绝的订单没有带活动的直接返回
        if (CollectionUtils.isEmpty(orderLineSDOList)) {
            log.error("拒绝的订单没有带活动的直接返回");
            return Result.success(true);
        }

        Map<String, OrderLineSDO> collect = Nullable.stream(orderLineSDOList).collect(Collectors.toMap(OrderLineSDO::getId, o -> o));

        for (String id : affectLineIds) {
            OrderLineSDO orderLineSDO = collect.get(id);
            if (Objects.isNull(orderLineSDO)) {
                log.error("ID对应的销售订单对象为空");
                continue;
            }
            if (MapUtils.isEmpty(orderLineSDO.getFeatures())) {
                log.error("features中信息为空");
                continue;
            }
            Map<String, String> features = orderLineSDO.getFeatures();
            if (StringUtils.isEmpty(features.get("activityDteails"))) {
                log.error("features中未记录活动信息信息");
                continue;
            }

            //判断是否为赠品行
            if ("gift".equals(features.get("giftFlag"))) {
                continue;
            }

            //获取预报订单子单ID
            if (StringUtils.isEmpty(features.get("forecastSubId"))) {
                return Result.fail("888", "feature中预报子订单不能为空");
            }
            String forecastSubId = features.get("forecastSubId");

            List<ActivitySDO> activitySDOS = JSONObject.parseArray(features.get("activityDteails"), ActivitySDO.class);
            if (CollectionUtils.isEmpty(activitySDOS)) {
                log.error("活动信息为空");
                continue;
            }

            // TBD 增加序列号指定回退活动
            final String sequenceNo = features.get("sequenceNo");

            List<CoverActivityInfoRequest>  coverActivityInfoRequestList = activitySDOS.stream().map(activitySDO -> {
                CoverActivityInfoRequest coverActivityInfoRequest = new CoverActivityInfoRequest();
                coverActivityInfoRequest.setClientId(orderSDO.getReceiveAddressCode());
                coverActivityInfoRequest.setMainOrderId(orderSDO.getFrontOrderId());
                coverActivityInfoRequest.setSubOrderId(forecastSubId);
                coverActivityInfoRequest.setOrderType(orderSDO.getOrderType());
                coverActivityInfoRequest.setActivityId(activitySDO.getActivityCode());

                CoverActivityTermRequest coverActivityTermRequest = new CoverActivityTermRequest();
                coverActivityTermRequest.setActivityTermId(activitySDO.getActivityTermid());


                ActivityItemInfo activityItemInfo = new ActivityItemInfo();
                if (StringUtils.isNotBlank(orderLineSDO.getScItemSDO().getScItemId()) && Objects.nonNull(orderLineSDO.getScItemSDO())) {
                    activityItemInfo.setItemId(orderLineSDO.getScItemSDO().getScItemId());
                    activityItemInfo.setItemQuantity(orderLineSDO.getScItemSDO().getQuantity());
                    activityItemInfo.setItemPrice(orderLineSDO.getScItemSDO().getUnitPrice());
                    activityItemInfo.setSalesUnit(orderLineSDO.getScItemSDO().getSaleUnit());
                    activityItemInfo.setStockUnit(orderLineSDO.getScItemSDO().getInventoryUnitCode());
                    activityItemInfo.setConversionUnit(orderLineSDO.getScItemSDO().getUnitConvert());
                }

                coverActivityTermRequest.setItem(activityItemInfo);
                coverActivityInfoRequest.setCoverActivityTermRequest(coverActivityTermRequest);

                // TBD 活动回退时需要把seqNo传回去
                coverActivityInfoRequest.setSequenceNo(sequenceNo);

                return coverActivityInfoRequest;
            }).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(coverActivityInfoRequestList)) {
                coverActivityInfoRequests.addAll(coverActivityInfoRequestList);
            }
        }

        //调用回补活动接口
        CoverActivityRequest coverActivityRequest = new CoverActivityRequest();
        coverActivityRequest.setCoverActivityInfoList(coverActivityInfoRequests);
        Map<String, String> features = new HashMap<>();
        features.put("codeFlag", PlatformCodeFlagEnum.INNER_CODE_TO_OUT_CODE.getCode());
        coverActivityRequest.setFeatures(features);
        Result<CoverInActivityResponse> coverInActivityResponseResult = applicationContext.getBean(ActivityWriteServiceImpl.class)
                .activityCoverExpand(coverActivityRequest);
        log.info("coverInActivityResponseResult " + JSONObject.toJSONString(coverInActivityResponseResult.getResult()));
        if (!coverInActivityResponseResult.isSuccess()){
            return Result.fail("OTS-08-002-01-16-003","活动回补失败!");
        }
        //        try {
//            this.activityCoverExpand(coverActivityRequest);
//        } catch (Exception e) {
//            log.error("coverInActivityResponseResult 回退结果:" + e);
//            //return Result.fail("888", e.getMessage());
//        }



        return Result.success(true);

    }


    /**
     * 校验活动回补参数
     * @param request
     */
    private static void checkActivity(CoverActivityInfoRequest request) {
        if(Objects.isNull(request)){
            log.error("活动参数不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }


        if(StringUtils.isBlank(request.getMainOrderId())){
            log.error("参与活动的主订单编号不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }


        if(StringUtils.isBlank(request.getSubOrderId())){
            log.error("参与活动的子订单编号不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }


        if(StringUtils.isBlank(request.getActivityId())){
            log.error("活动编号不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }

        if(Objects.isNull(request.getCoverActivityTermRequest())){
            log.error("活动项目不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }

        if(StringUtils.isBlank(request.getCoverActivityTermRequest().getActivityTermId())){
            log.error("活动项目编号不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }

        if(Objects.isNull(request.getCoverActivityTermRequest().getItem())){
            log.error("参与活动的商品参数不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }

        if(StringUtils.isBlank(request.getCoverActivityTermRequest().getItem().getItemId())){
            log.error("参与活动的商品编号不能为空 = {}",request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }

        if (StringUtils.isBlank(request.getSequenceNo())) {
            log.error("校验活动参数中的 SequenceNo不能为空，request={}", request);
            log.error("ActivityWriteServiceImpl#activityCover_fail");
            throw new FacadeException("OTS-08-002-01-16-008");
        }

    }
}
